package com.enba.rbacadmin.module.auth.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.enba.boot.core.enums.YesOrNoEnum;
import com.enba.boot.core.exception.BizException;
import com.enba.boot.core.utils.TreeNode;
import com.enba.boot.core.utils.TreeUtils;
import com.enba.rbacadmin.enums.MenuTypeEnum;
import com.enba.rbacadmin.manager.UserMenuManager;
import com.enba.rbacadmin.module.auth.controller.req.MenuAddUpdateReq;
import com.enba.rbacadmin.module.auth.controller.resp.MenuTreeNodeResp;
import com.enba.rbacadmin.module.auth.controller.resp.MenuTreeTableNodeResp;
import com.enba.rbacadmin.module.auth.entity.Menu;
import com.enba.rbacadmin.module.auth.mapper.MenuMapper;
import com.enba.rbacadmin.module.auth.service.IMenuService;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 菜单表 服务实现类
 *
 * @author 恩爸编程
 * @since 2025-02-28
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

  @Autowired private UserMenuManager usrMenuManager;

  @Override
  public List<TreeNode> getUserMenu(Long userId) {
    return usrMenuManager.getUserMenu(userId);
  }

  @Override
  public List<TreeNode> getAllMenu() {
    return usrMenuManager.getAllMenu();
  }

  @Override
  public List<TreeNode> getAllTreeTableMenu() {
    // 获取扁平数据并转换成树形结构
    return TreeUtils.<Menu>buildTree(
        () ->
            this.getBaseMapper()
                .selectList(
                    Wrappers.<Menu>lambdaQuery().eq(Menu::getDeleted, YesOrNoEnum.NO.getCode())),
        menuList ->
            menuList.stream()
                .map(
                    e -> {
                      MenuTreeTableNodeResp orgTreeNodeResp =
                          new MenuTreeTableNodeResp(e.getId(), e.getParentId(), e.getMenuName());
                      orgTreeNodeResp.setParentId(e.getParentId());
                      orgTreeNodeResp.setName(e.getMenuName());
                      orgTreeNodeResp.setType(e.getType());
                      orgTreeNodeResp.setPerms(e.getPerms());
                      orgTreeNodeResp.setUrl(e.getUrl());
                      orgTreeNodeResp.setIcon(e.getIcon());
                      orgTreeNodeResp.setStatus(e.getStatus());
                      orgTreeNodeResp.setLayChecked(false);
                      return orgTreeNodeResp;
                    })
                .collect(Collectors.toList()));
  }

  @Override
  public boolean saveOrUpdate(MenuAddUpdateReq menu) {
    Long id = menu.getId();
    if (id == null) {
      // 新增
      Menu menuEntity = new Menu();
      menuEntity.setMenuName(menu.getMenuName());
      menuEntity.setParentId(menu.getParentId());
      menuEntity.setPerms(menu.getPerms());
      menuEntity.setOrderNum(menu.getOrderNum());
      menuEntity.setUrl(menu.getUrl());
      menuEntity.setIcon(menu.getIcon());
      menuEntity.setStatus(menu.getStatus());

      if (menu.getParentId() == null || menu.getParentId() == 0) {
        menuEntity.setType(MenuTypeEnum.DIR.getCode());
      } else {
        Menu parentMenu = this.getById(menu.getParentId());
        if (Objects.isNull(parentMenu)) {
          BizException.throwEx("父级ID不存在");
        }

        Integer type = parentMenu.getType();
        if (type.equals(MenuTypeEnum.DIR.getCode())) {
          menuEntity.setType(MenuTypeEnum.MENU.getCode());
        } else if (type.equals(MenuTypeEnum.MENU.getCode())) {
          menuEntity.setType(MenuTypeEnum.BUTTON.getCode());
        } else {
          BizException.throwEx("父级菜单类型错误");
        }
      }
      return this.save(menuEntity);
    } else {
      // 更新
      Menu menuEntity = new Menu();
      menuEntity.setId(menu.getId());
      menuEntity.setMenuName(menu.getMenuName());
      menuEntity.setPerms(menu.getPerms());
      menuEntity.setOrderNum(menu.getOrderNum());
      menuEntity.setUrl(menu.getUrl());
      menuEntity.setIcon(menu.getIcon());
      menuEntity.setStatus(menu.getStatus());
      return this.updateById(menuEntity);
    }
  }

  @Override
  public List<TreeNode> getRoleAllMenuIdSet(Long roleId) {
    // 用户拥有的菜单权限
    Set<Long> userAllMenuIdSet = usrMenuManager.getRoleAllMenuIdSet(roleId);

    // 所有菜单权限
    List<TreeNode> allMenuList = usrMenuManager.getAllMenu();

    for (TreeNode node : allMenuList) {
      setPropertyWithStream((MenuTreeNodeResp) node, userAllMenuIdSet);
    }

    return allMenuList;
  }

  /**
   * @param node 菜单节点
   * @param userAllMenuIdSet 用户拥有的菜单权限
   */
  private void setPropertyWithStream(MenuTreeNodeResp node, Set<Long> userAllMenuIdSet) {
    // 判断当前节点是否为用户拥有
    boolean contains = userAllMenuIdSet.contains(node.getId());

    node.setLayChecked(contains);

    Optional.ofNullable(node.getChildren())
        .ifPresent(
            children -> {
              children.forEach(
                  child -> setPropertyWithStream((MenuTreeNodeResp) child, userAllMenuIdSet));
            });
  }
}
